#ifndef __LOG_HPP
#define __LOG_HPP


#include <iostream>
#include <ctime>
#include <cstdarg>
#include <memory>
enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

// 日志是有格式的
// 日志等级 时间 代码所在的文件名/行数 日志的内容
class LogType
{
private:
    static std::string LevelToString(int level)
    {
        switch (level)
        {
        case DEBUG:
            return "Debug";
        case INFO:
            return "Info";
        case WARNING:
            return "Warning";
        case ERROR:
            return "Error";
        case FATAL:
            return "Fatal";
        default:
            return "Unknown";
        }
    }
    static std::string GetTime()
    {
        time_t t = time(nullptr);
        struct tm *t_struct = localtime(&t);
        // t_struct可以把t转化为年月日。。。
        std::string time = std::to_string(t_struct->tm_year + 1900) + "-";
        time += std::to_string(t_struct->tm_mon + 1) + "-";
        time += std::to_string(t_struct->tm_mday) + " ";
        time += std::to_string(t_struct->tm_hour) + ":";
        time += std::to_string(t_struct->tm_min) + ":";
        time += std::to_string(t_struct->tm_sec);
        return time;
    }

public:
    LogType()
    {
    }
    void operator()(int level, int line, const std::string &filename, const char *format, ...)
    {
        _level = level;
        _line = line;
        _filename = filename;
        va_list args;
        va_start(args, format);
        char buffer[1024];
        vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        _log_content = buffer;
        FILE *fp = stdout;
        if (_is_save == true)
        {
            fp = fopen("./log.txt", "a+");
            if (fp == nullptr)
            {
                std::cerr << "save error!" << std::endl;
                return;
            }
        }

        fprintf(fp, "[%s][%s][%s:%d]:%s", LevelToString(_level).c_str(), GetTime().c_str(), _filename.c_str(), _line, _log_content.c_str());
        if(fp != stdout)
            fclose(fp);
    }
    static void IsSave(bool is)
    {
        if (is)
            _is_save = true;
        else
            _is_save = false;
    }

protected:
    int _level;
    int _line;
    std::string _filename;
    std::string _log_content;
    static bool _is_save;
};
bool LogType::_is_save = false;

#endif